/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <基本类型.h>
#include <向量.h>

#include <string>
#include <vector>
#include <stdio.h>

//#include <boost/filesystem.hpp>



void* f_打开文件(uint32* size, const std::string path);

void f_保存文件(const void* data[], const uint32* size, const uint32 num, const std::string path, const bool 是否备份保存 = true);

void f_写入文件(FILE* f, const std::vector<float32>& data);
void f_读入文件(FILE* f, std::vector<float32>* data);

void f_写入文件(FILE* f, const std::vector<std::vector<float32>>& data);
void f_读入文件(FILE* f, std::vector<std::vector<float32>>* data);



//void f_写入序列到文件(FILE* f, const std::vector<vec3>& data);
//void f_读入文件(FILE* f, std::vector<vec3>* data);






template<typename T>
void file_写入序列到文件(FILE* f, const std::vector<T>& data) {
	uint32 num = data.size();
	fwrite(&num, sizeof(uint32), 1, f);
	if (num) {
		fwrite(data.data(), sizeof(T), num, f);
	}
}
template<typename T>
uint32 file_读取序列到文件(FILE* f, std::vector<T>* data) {
	uint32 num = 0;
	fread(&num, sizeof(uint32), 1, f);
	if (num) {
		(*data).resize(num);
		fread((*data).data(), sizeof(T), (*data).size(), f);
	}
	return num;
}





template<typename T>
void f_写入文件(FILE* f, T& data) {
	fwrite(&data, sizeof(T), 1, f);
}
template<typename T>
void f_读取文件(FILE* f, T* data) {
	fread(data, sizeof(T), 1, f);
}


typedef void(*fp_file_backupSave)(FILE* f);
void f_file_备份保存文件(const std::string& path, fp_file_backupSave call, bool 是否备份保存 = true);

/*template<typename T>
void f_file_备份保存文件(const std::string path, const T& fun, bool 是否备份保存 = true) {
	std::filesystem::path tmpPath(path);

	bool 是否有老文件 = false;
	std::string 保存路径 = path;
	std::string 文件名 = tmpPath.stem().string();
	std::string 临时文件路径 = tmpPath.parent_path().string() + "/tme_" + 文件名 + ".tmp";
	
	//目录是否存在
	if (std::filesystem::exists(tmpPath.parent_path().string()) == false) {
		std::filesystem::create_directories(tmpPath.parent_path().string());
	}

	if (是否备份保存) {
		if (std::filesystem::exists(tmpPath)) {
			保存路径 = 临时文件路径;
			是否有老文件 = true;
		}
	}


	FILE* f;
	f = fopen(保存路径.c_str(), "wb");
	if (f) {
		fun(f);
	}
	fclose(f);




	if (是否有老文件) {
		//把老文件备份
		std::filesystem::path 备份文件名(tmpPath.parent_path().string() + "/Backup_" + 文件名 + ".tmp");
		std::filesystem::rename(tmpPath, 备份文件名);

		//临时文件改层主文件名
		std::filesystem::rename(保存路径, tmpPath);
	}

}*/



template<typename T>
void f_读文本文件(const std::string path, const T& fun) {
	FILE* f = fopen(path.c_str(), "rb");
	if (f) {
		fun(f);
		fclose(f);
	}
}

template<typename T>
void f_读文件(const std::string path, const T& fun) {
	FILE* f = fopen(path.c_str(), "rb");
	if (f) {
		fun(f);
		fclose(f);
	}
}




static std::vector<char> f_读文本文件(const std::string& filename) {
	FILE* f = fopen(filename.c_str(), "r");

	fseek(f, 0L, SEEK_END);

	uint64 size = ftell(f);
	//void* data = malloc((*size + 1) * sizeof(uint8));
	//void* data = malloc((size) + 1);
	std::vector<char> buffer(size);

	if (size) {
		rewind(f);
		fseek(f, 0L, SEEK_SET);
		fread(buffer.data(), size, 1, f);
	}
	fclose(f);

	return buffer;
}

template<typename T>
static std::vector<T> f_读文件(const std::string& filename) {
	std::vector<T> buffer;

	FILE* f = fopen(filename.c_str(), "rb");
	if (f) {
		fseek(f, 0L, SEEK_END);

		uint64 size = ftell(f);
		buffer.resize(size);

		if (size) {
			rewind(f);
			fseek(f, 0L, SEEK_SET);
			fread(buffer.data(), size, 1, f);
		}
		fclose(f);
	}
	else {
		std::cout<<"load spv file error : "<< filename << std::endl;
	}

	return buffer;
}





static std::vector<uint32> f_读文本文件_i32(const std::string& filename) {
	std::vector<char> buffer = f_读文本文件(filename);

	if (buffer.size()) {
		buffer.push_back(0);
	}
	std::vector<uint32> ui32_buf(buffer.size());
	memcpy(ui32_buf.data(), buffer.data(), buffer.size() * sizeof(uint8));
	//ui32_buf.assign(buffer.begin(), buffer.end());
	return ui32_buf;
}














inline void f_file_保存字符串(FILE* F, const std::string& str) {
	uint32 size = uint32(str.length());
	fwrite(&size, sizeof(uint32), 1, F);
	if (size) fwrite(str.c_str(), sizeof(uint8), size, F);
}

inline void f_file_保存字符串(FILE* F, const std::wstring& str) {
	uint32 size = uint32(str.size());
	fwrite(&size, sizeof(uint32), 1, F);
	if (size) fwrite(str.c_str(), sizeof(wchar_t), size, F);
}

inline std::string f_读取字符串(FILE* F) {
	uint32 size = 0;
	fread(&size, sizeof(uint32), 1, F);
	std::string text;
	if (size) {
		text.resize(size);
		fread(&(text[0]), sizeof(int8), size, F);
	}
	return text;
}

inline std::wstring f_file_读取字符串(FILE* F) {
	uint32 size = 0;
	fread(&size, sizeof(uint32), 1, F);
	std::wstring text;
	if (size) {
		text.resize(size);
		fread(&(text[0]), sizeof(wchar_t), size, F);
	}
	return text;
}


inline void f_file_保存文本(FILE* f, const std::string& str) {
	uint32 size = uint32(str.length());
	if (size) fwrite(str.c_str(), sizeof(uint8), size, f);
}

inline void f_file_保存文本(FILE* f, const std::vector<int32>& str) {
	uint32 size = str.size();
	if (size) fwrite(str.data(), sizeof(int32), size, f);
}

inline std::string f_file_读取文本(FILE* f) {
	fseek(f, 0L, SEEK_END);
	uint64 size = ftell(f);
	
	rewind(f);
	fseek(f, 0L, SEEK_SET);

	std::string str;
	if (size) {
		str.resize(size);
		fread(str.data(), size, 1, f);
	}
	return str;
}


template<typename T>
inline void file_单数值保存(FILE* F, const T& value) {
	fwrite(&value, sizeof(T), 1, F);
	//fwrite(str.c_str(), sizeof(uint8), size, F);
}


template<typename T>
Inline void file_单数值读取(FILE* F, T& value) {
	fread((void*)&value, sizeof(T), 1, F);
	//fwrite(str.c_str(), sizeof(uint8), size, F);
}




